Gazebo Sim 架构 — Gazebo Harmonic 文档
Gazebo Sim
Gazebo Sim 是 Gazebo 的应用程序入口,通常包含所有其他 Gazebo 库的使用。作为可执行文件,它通过启动两个进程来运行模拟:后端服务器进程和前端客户端进程。
Gazebo Sim 的核心功能是客户端与服务器之间的通信,以及它加载的各种插件,这些插件有助于模拟。插件是在运行时加载的库。它们允许 Gazebo Sim 使用其他 Gazebo 库。Gazebo 框架中有许多类型的插件。例如,有些插件可以引入新的物理引擎或渲染引擎。但是,就本文档而言,任何提及的插件均指 Gazebo Sim 服务器和 GUI 插件。
由于插件在运行时加载,因此无需重新编译 Gazebo 即可添加或删除插件。Gazebo Sim 默认自带许多插件( 服务器插件 、 Gazebo GUI 插件 、 Gazebo Sim GUI 插件 等等),所有这些插件都是 可选的,用户可以自行移除。用户还可以添加更多插件,甚至可以编写自己的插件,并将其编译成库文件。
Gazebo 库是模块化的。插件允许 Gazebo Sim 使用其他库。例如, Gazebo Physics 和 Gazebo Sim 彼此独立,因此 Gazebo Sim 有一个物理插件,它使用 Gazebo Physics 作为库,并融入了 Gazebo 的特性,使物理系统成为一个在模拟循环中运行的系统。
Gazebo Physics 库仅用于物理插件,不用于其他插件或 Gazebo Sim 的核心。有些库仅由一个插件使用,或每个进程(前端和后端)各使用一个。然而,有些基础库被所有插件使用,例如 Gazebo Common ,它为所有插件提供通用功能,例如日志记录、字符串操作、文件系统交互等。其他此类库包括 Gazebo Plugin 、 Gazebo Math 、 SDFormat 等。
每个版本的 Gazebo 中,前端和后端进程中都会默认加载某些插件。许多其他插件是可选的。一个常见的可选插件是传感器插件。可选插件和默认插件都可以随时移除或添加;Gazebo Sim 将继续运行,但功能会受到限制。 服务器配置 和 GUI 配置的 演示演示了这些功能。
模拟过程如下图所示,并在后面的后端和前端过程部分进一步解释。
后端服务器
Gazebo Sim 负责在后端(称为系统)加载插件。服务器运行一个实体组件系统架构(参见 Gazebo Sim 术语 )。后端通常会有多个系统负责模拟中的所有功能——计算物理、记录日志、接收用户命令等等。
系统作用于实体及其组件。实体是模拟场景中的任何事物(模型、链接、光源、角色等),组件是它们的特征(姿势、名称、几何形状等)。服务器插件可以访问所有实体及其组件,并对这些组件进行修改。例如,用户可以编写一个系统,通过在实体上设置组件来向该实体施加力,物理系统会接收该力并通过施加力使实体实际移动做出反应。修改实体和组件是服务器插件之间相互通信的方式。
实体组件系统在 Gazebo Sim 中是独立的,并且系统作用于实体及其组件。由于其他 Gazebo 库无法直接访问实体和组件,因此应在系统中使用其他 Gazebo 库,以便服务器插件可以与这些库共享实体(及其组件)。例如,物理系统与 Gazebo 物理库共享实体和组件,以便在实体和组件上实现物理效果。
运行系统的后端有一个循环,其中一些系统负责提议对实体及其组件进行更改,而其他系统则负责处理和应用这些更改。这被称为“模拟循环”。后端的实体组件管理器 (ECM) 提供对实体和组件进行实际查询和更新的功能。
物理系统 、 用户命令 和 场景广播系统 都是后端默认启动的系统。然而,如前所述,即使是默认系统也可以添加到模拟循环中或从模拟循环中移除( 服务器配置 教程介绍了如何自定义默认系统)。对于任何其他功能,例如传感器数据处理,则必须加载额外的系统。例如,如果您需要生成利用渲染传感器的传感器数据,则需要加载 传感器系统 。但是,这些数据的可视化则由客户端插件完成。
通信
任何跨越进程边界的信息(无论是使用场景广播器从后向前传输,还是使用用户命令从前向后传输)都必须经过 通信库 Gazebo Transport 。进程之间的同步由场景广播器执行,它是一个服务器端的 Gazebo Sim 插件,使用 Gazebo Transport 和 Gazebo Messages 库将消息从服务器发送到客户端。消息本身由 Gazebo Messages 提供,而用于创建交换消息的发布者和订阅者的框架则来自 Gazebo Transport。
场景广播系统负责从后端不断变化的模拟循环中获取世界状态(所有实体及其组件值),将这些信息打包成非常紧凑的消息,并定期将其发送到前端进程。虽然可以省略场景广播系统,但这意味着无法在前端实现数据可视化,而可视化有助于节省计算能力。
除了场景广播器向客户端发送状态消息外,客户端还可以使用用户命令系统(另一个后端插件)向服务器发出请求。它还利用了 Gazebo Transport 和 Gazebo Messages 库。用户命令系统提供一些服务,前端 GUI 可以请求这些服务来插入、删除、移动(等等)模型、灯光和其他实体,并将响应发送回 GUI,确认已收到并执行这些请求。
一些非默认插件能够向服务器-客户端进程之外的其他进程发送或接收消息。例如,服务器端传感器插件会在服务器-客户端进程之外发布消息,而服务器端 diff-drive 插件则会从客户端以外的进程接收信息。例如,这些插件可以与之通信的进程之一是 ROS 。
前端客户端
客户端进程(本质上是 GUI)也包含多个插件,其中一些是默认加载的,另一些可以添加,还有一些是可选的。所有前端插件都使用 Gazebo GUI 库。客户端本身也依赖于 Gazebo GUI。有一些可视化插件可以创建 GUI 窗口、添加按钮和其他交互功能,还有一个 3D 场景插件利用 Gazebo Rendering 创建用户看到的场景。
前端插件通常使用事件 相互通信 。事件类似于消息,但它们是同步处理的。例如, Render
事件由 3D 场景在其渲染线程即将渲染之前发出;这使得其他插件有机会在渲染时刻在该线程上执行代码,这对于编辑 3D 场景非常有用。其他类似的事件例如在用户右键单击或悬停在场景上时发出。
所有前端插件都可以访问场景广播系统从后端提供的压缩消息中的实体和组件信息。客户端的实体组件管理器执行实际的消息解包,并将实体和组件信息分发给相关插件。可视化系统就是这样根据后端计算结果进行更新的。在客户端,插件仅对实体和组件信息做出反应,而不会与其进行交互。
如上一节所述,GUI 可以使用服务器的用户命令系统将命令发送回服务器。例如,如果用户想要通过 GUI 界面插入新模型,就会出现这种情况。用户命令接收来自 GUI 的请求并进行处理,然后将结果添加到模拟循环中的实体和组件中。